﻿//========================================
// All rights reserved (C) 2017-2100
// CLR 版本：	4.0.30319.42000
// 命名空间:	SFJDService.TransportHandle
// 文 件 名：	SendThreads
// 作    者：	WooG
// 联系方式：	wooglle@163.com
// 创建时间：	2018/6/20 12:18:55
//========================================
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace SFJDService.TransportHandle
{
    public static class SendThreads
    {
        private const int maxThread = 30;
        private static int socketDelay = 5000;
        private static int runningThread = 0;
        private static int[] ports;
        private static int socketIndex = 0;
        private static object objLock1 = new object();
        private static object objLock2 = new object();
        private static Socket[] sockets;
        private static IPEndPoint[] endPoints;
        //private static Dictionary<FileByteIndex, Thread> dictionary = new Dictionary<FileByteIndex, Thread>(maxThread);

        public static void SetPorts(string ip, int[] vs)
        {
            ports = vs;
            sockets = new Socket[ports.Length];

            endPoints = new IPEndPoint[ports.Length];
            for(int i = 0; i < ports.Length; i++)
            {
                Socket socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                socketClient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
                sockets[i] = socketClient;
                
                IPEndPoint iep = new IPEndPoint(IPAddress.Broadcast, ports[i]);
                endPoints[i] = iep;
            }
        }

        public static void CheckHandle(PacketFileCheck fileCheck)
        {
            if (fileCheck.Boolean)
            {
                Runtime.Printf("数据包已完成 " + fileCheck.ToString());
                try
                {
                    //lock (dictionary)
                    //{
                    //    FileByteIndex key = new FileByteIndex(fileCheck);
                    //    dictionary[key].Abort();
                    //    dictionary.Remove(key);
                    //    Thread.Sleep(10);
                    //    runningThread--;
                    //    socketDelay = socketDelay + 10 > 5000 ? 5000 : socketDelay + 10;
                    //}
                }
                catch(KeyNotFoundException e)
                {
                    ;
                }
                catch(Exception e)
                {
                    throw;
                }
            }
            else
            {
                Runtime.Printf("数据包错误 " + fileCheck.ToString());
            }
        }

        public static void Send(PacketFileTransport packet)
        {
            while (runningThread >= maxThread) ;//线程过多时等待
                                                //while (dictionary.Count >= maxThread) ;
            Thread thread = new Thread(new ParameterizedThreadStart(SendPacket));
            thread.Start(packet);
            //dictionary.Add(new FileByteIndex(packet), thread);
            lock (objLock2)
            {
                runningThread++;
            }
        }

        private static void SendPacket(object obj)
        {
            PacketFileTransport packet = (PacketFileTransport)obj;
            try
            {
                byte[] byts = packet.ToBytes();
                Runtime.Printf("发出数据包 " + packet.ToString());
                //while (true)
                //{
                    
                //}
                int index = getSocketIndex();
                sockets[index].SendTo(byts, endPoints[index]);
                lock (objLock2)
                {
                    runningThread--;
                }
                //Thread.Sleep(socketDelay);
            }
            catch
            {
                throw;
            }
        }

        private static int getSocketIndex()
        {
            lock (objLock1) //加锁 使不同线程保持同步
            {
                socketIndex++;
                socketDelay = socketDelay - 10 < 200 ? 200 : socketDelay - 10;
                if (socketIndex + 1 > sockets.Length)
                {
                    socketIndex = 0;
                    return 0;
                }
                else
                {
                    return socketIndex;
                }
            }
        }

        public static void ShutdownSocket()
        {
            //foreach(Socket sock in sockets)
            //{
            //    sock.Close();
            //}
        }
    }
}